import java.util.ArrayList;
import java.util.List;

/**
 * 46. 全排列
 */
public class Solution_46 {
    /**
     * 题解：
     * https://leetcode-cn.com/problems/permutations/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liweiw/
     */
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        if (nums.length == 0) {
            return ans;
        }

        boolean[] used = new boolean[nums.length];
        List<Integer> path = new ArrayList<>();

        dfs(nums, 0, path, used, ans);
        return ans;
    }

    /**
     * 
     * @param nums
     * @param depth 表示当前程序递归到第几层
     * @param path
     * @param used  记录相应位置的数字是否已被选择
     * @param ans
     */
    private void dfs(int[] nums, int depth, List<Integer> path, boolean[] used, 
                     List<List<Integer>> ans) {
        int len = nums.length;
        if (depth == len) {
            ans.add(new ArrayList<>(path));
            return;
        }

        // 在非叶子结点处，产生不同的分支，这一操作的语义是：
        // 在还未选择的数中依次选择一个元素作为下一个位置的元素，这显然得通过一个循环实现。
        for (int i = 0; i < len; i++) {
            if (!used[i]) {
                path.add(nums[i]);
                used[i] = true;
                dfs(nums, depth + 1, path, used, ans);
                // 注意：下面这两行代码发生 「回溯」，回溯发生在从 深层结点 回到 浅层结点 的过程，
                // 代码在形式上和递归之前是对称的
                used[i] = false;
                path.remove(path.size() - 1);
            }
        }
    }

    public static void main(String[] args) {
        Solution_46 solution = new Solution_46();
        int[] nums = { 1, 2, 3 };
        List<List<Integer>> ans = solution.permute(nums);
        System.out.println(ans);
    }
}
